/*
 * author      : dormi330
 * date        : 2018/7/6
 * description : 添加包裹操作
 */

package com.deep.trade.application.order;

import com.deep.trade.adaptor.required.IdService;
import com.deep.trade.common.CommonUtils;
import com.deep.trade.common.TradeException;
import com.deep.trade.domain.order.*;
import com.deep.trade.order.dto.InDtoEachParcel;
import com.deep.trade.order.dto.ParcelItem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Service
public class AddParcelService {

    private Logger logger = LoggerFactory.getLogger(this.getClass().getName());

    private OrderQueryRepository orderQueryRepository;
    private OrderRepository orderRepository;
    private IdService idService;

    @Autowired
    public AddParcelService(
            OrderQueryRepository orderQueryRepository
            , OrderRepository orderRepository
            , IdService idService) {
        this.orderQueryRepository = orderQueryRepository;
        this.orderRepository = orderRepository;
        this.idService = idService;
    }

    /**
     * 添加包裹
     *
     * @param inDtoEachParcelList 包裹列表
     */
    @Transactional
    public void addParcel(List<InDtoEachParcel> inDtoEachParcelList) throws TradeException {
        logger.info("{}, inDtoEachParcelList={}", CommonUtils.currentClassAndMethod(), inDtoEachParcelList);

        if (null == inDtoEachParcelList || 0 == inDtoEachParcelList.size())
            throw new TradeException("parcel null or empty");

        // 包裹列表中必须是同一个 tradeOrder的东西
        TradeOrder tradeOrder = orderQueryRepository.tradeOrderOfId(inDtoEachParcelList.get(0).getTradeOrderId());
        if (null == tradeOrder) throw new TradeException("no such trade order");
        orderQueryRepository.fulfilTradeOrderSku(tradeOrder);

        if (inDtoEachParcelList.size() == 1 && null == inDtoEachParcelList.get(0).getParcelItemList()) {
            // 整个订单一个包裹
            InDtoEachParcel inDtoEachParcel = inDtoEachParcelList.get(0);
            singleParcelForTradeOrder(inDtoEachParcel, tradeOrder);
            assembleParcelAndSave(inDtoEachParcel, tradeOrder);
        } else {
            // 分包裹
            for (InDtoEachParcel inDtoEachParcel : inDtoEachParcelList) {
                assembleParcelAndSave(inDtoEachParcel, tradeOrder);
            }
        }

        // 完成之后,更新 tradeOrder 自己
        if (tradeOrder.parcelAdded()) {
            orderRepository.updateTradeOrderStatus(tradeOrder);
        }
    }

    // 会有性能问题, 但是目前不考虑, 优先可读性
    private void assembleParcelAndSave(InDtoEachParcel inParcel, TradeOrder tradeOrder) throws TradeException {
        String tradeOrderId = inParcel.getTradeOrderId();
        if (null == tradeOrderId) throw new TradeException("tradeOrderId cannot be null");
        if (!tradeOrder.getId().equals(inParcel.getTradeOrderId())) {
            throw new TradeException("all parcel must belong to same trade order");
        }

        // new entity
        OrderParcel orderParcel = new OrderParcel();
        // TODO createdBy updatedBy
        orderParcel.initStartStatus();
        orderParcel.setId(idService.uuid());
        orderParcel.setTradeOrderId(tradeOrderId);
        orderParcel.setTrackingNo(inParcel.getTrackingNo());
        orderParcel.setTrackingNoImg(inParcel.getTrackingNoImg());
        orderParcel.setLogisticsCompanyCode(inParcel.getLogisticsCompanyCode());
        orderParcel.setLogisticsCompanyName(inParcel.getLogisticsCompanyName());

        // entiy 字段填充
        List<ParcelItem> parcelItemList = inParcel.getParcelItemList();
        for (ParcelItem parcelItem : parcelItemList) {
            TradeOrderSku tradeOrderSku = tradeOrder.findSku(parcelItem.getTradeOrderSkuId());
            if (null == tradeOrderSku) throw new TradeException("TradeOrderSku not found");
            orderParcel.addParcelItem(tradeOrderSku, parcelItem.getQuantity());
        }

        orderParcel.packToString();                 // 存储前处理, 手动序列化
        orderRepository.addParcel(orderParcel);     // 存储
    }

    // 如果一个包裹中的 parcelItem 为null, 则认为它 是 包含整个订单的 sku
    private void singleParcelForTradeOrder(InDtoEachParcel inParcel, TradeOrder tradeOrder) {
        List<ParcelItem> parcelItemList = null;
        try {
            parcelItemList = tradeOrder.getSkuList().stream()
                    .map(tradeOrderSku -> new ParcelItem(tradeOrderSku.getId(), tradeOrderSku.getQuantity()))
                    .collect(Collectors.toList());
        } catch (Exception e) {
            e.printStackTrace();
        }
        inParcel.setParcelItemList(parcelItemList);
    }
}
